﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitDimensionText.OneKeyPlanDim.LevelDim;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimData
{
	public class DbGutter : DbDimBase
	{
		public DbGutter(Group Ditch, Autodesk.Revit.DB.Document doc)
		{
			this.m_Ditch = Ditch;
			this.m_doc = doc;
		}

		public override bool CreateSizeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSizeDim(doc))
			{
				return false;
			}
			List<ElementId> list = this.m_Ditch.GetMemberIds().ToList<ElementId>();
			if (list.Count < 1)
			{
				return false;
			}
			Dictionary<double, List<FamilyInstance>> dic = new Dictionary<double, List<FamilyInstance>>();
			this.DitchClassification(list, dic);
			this.CreateMaxLengthDitchDim(dic);
			return true;
		}

		private void SetDimPosition(Dimension newDim, Line lineRef, XYZ dir)
		{
			List<CurveLoop> componentAndSizeAndSlopeOcclusionArea = OcclusionArea.GetInstance().GetComponentAndSizeAndSlopeOcclusionArea();
			List<CurveLoop> sizeDimCurveLoop = OcclusionArea.GetSizeDimCurveLoop(newDim);
			XYZ origin = lineRef.Origin;
			XYZ ptEnd = origin;
			List<CurveLoop> list = new List<CurveLoop>();
			for (int i = 0; i < 9; i++)
			{
				ptEnd = CommonInterface.GetNumCorrespondingOffsetPoint(i, Common.MMToFeet(600.0) * (double)this.m_doc.ActiveView.Scale / 100.0, origin, dir);
				list = CommonInterface.MoveLstCurve(sizeDimCurveLoop, origin, ptEnd);
				bool flag = false;
				using (List<CurveLoop>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (CommonInterface.IsExistOcclusion(enumerator.Current, componentAndSizeAndSlopeOcclusionArea))
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				if (8 == i)
				{
					ptEnd = origin;
					break;
				}
			}
			OcclusionArea.GetInstance().m_lstSizeDimCvLoop.AddRange(list);
			CommonInterface.MoveElement(newDim, origin, ptEnd, this.m_doc);
		}

		private void GetWallMinDim(ref Element dimELem, ref XYZ ptOffset, ref double dMin, XYZ vtDitch, XYZ ptLocation)
		{
			foreach (Wall wall in KeyComponent.GetInstance().m_lstWall)
			{
				Curve curve = (wall.Location as LocationCurve).Curve;
				if (!(curve is Arc))
				{
					XYZ direction = (curve as Line).Direction;
					if (Geometry.IsParallel(direction, vtDitch, 1E-09))
					{
						Geometry.RotateTo(direction, Math.PI*.5, XYZ.BasisZ);
						Curve curve2 = curve.Clone();
						curve2.MakeUnbound();
						XYZ xyzpoint = curve2.Project(ptLocation).XYZPoint;
						double num = xyzpoint.DistanceTo(ptLocation);
						if (Geometry.LessThan(num, dMin))
						{
							dMin = num;
							ptOffset = xyzpoint;
							dimELem = wall;
						}
					}
				}
			}
		}

		private void CreateMaxLengthDitchDim(Dictionary<double, List<FamilyInstance>> dic)
		{
			foreach (KeyValuePair<double, List<FamilyInstance>> keyValuePair in dic)
			{
				double num = double.MinValue;
				double dWidth = double.MinValue;
				Element element = null;
				foreach (FamilyInstance familyInstance in keyValuePair.Value)
				{
					Parameter parameter = RevitElementExtension.GetParameter(familyInstance, "长度");
					if (parameter != null)
					{
						double num2 = parameter.AsDouble();
						if (Geometry.LessThan(num, num2))
						{
							num = num2;
							dWidth = keyValuePair.Key;
							element = familyInstance;
						}
					}
				}
				if (element != null)
				{
					FamilyInstance familyInstance2 = element as FamilyInstance;
					XYZ handOrientation = familyInstance2.HandOrientation;
					if (handOrientation != null)
					{
						XYZ vtNewOffset = Geometry.RotateTo(handOrientation, Math.PI*.5, XYZ.BasisZ);
						XYZ point = (familyInstance2.Location as LocationPoint).Point;
						if (point != null)
						{
							this.CreateParallelDim(num, dWidth, familyInstance2, handOrientation, vtNewOffset, point);
							this.CreateVerticalDim(familyInstance2, point);
						}
					}
				}
			}
		}

		private void CreateVerticalDim(FamilyInstance fi, XYZ ptLocation)
		{
			Grid grid = null;
			Wall wall = null;
			Parameter parameter = RevitElementExtension.GetParameter(fi, "长度");
			double num = 0.0;
			if (parameter != null)
			{
				num = parameter.AsDouble();
			}
			XYZ xyz = ptLocation + fi.HandOrientation * num;
			XYZ xyz2 = ptLocation;
			XYZ xyz3 = ptLocation;
			DbAxial dbAxial = null;
			if (base.GetDbAxialWithDir(fi.FacingOrientation, out dbAxial))
			{
				double num2 = 0.0;
				grid = dbAxial.GetGridNearestXZY(ptLocation, ref num2);
				double num3 = 0.0;
				Grid gridNearestXZY = dbAxial.GetGridNearestXZY(xyz, ref num3);
				if (Geometry.LessThan(num3, num2))
				{
					grid = gridNearestXZY;
					xyz2 = xyz;
				}
			}
			Element element = null;
			XYZ xyz4 = null;
			double maxValue = double.MaxValue;
			this.GetWallMinDim(ref element, ref xyz4, ref maxValue, fi.FacingOrientation, ptLocation);
			Element element2 = null;
			XYZ xyz5 = null;
			double maxValue2 = double.MaxValue;
			this.GetWallMinDim(ref element2, ref xyz5, ref maxValue2, fi.FacingOrientation, xyz);
			if (element != null && element2 != null)
			{
				if (Geometry.LessThan(maxValue, maxValue2))
				{
					wall = (element as Wall);
					xyz3 = ptLocation;
				}
				else
				{
					wall = (element2 as Wall);
					xyz3 = xyz;
				}
			}
			Element element3 = null;
			XYZ xyz6 = null;
			XYZ xyz7 = null;
			if (wall != null && grid != null)
			{
				Curve curve = grid.Curve.Clone();
				curve.MakeUnbound();
				XYZ xyzpoint = curve.Project(xyz2).XYZPoint;
				double num4 = xyzpoint.DistanceTo(xyz2);
				Curve curve2 = (wall.Location as LocationCurve).Curve.Clone();
				curve2.MakeUnbound();
				XYZ xyzpoint2 = curve2.Project(xyz2).XYZPoint;
				double num5 = xyzpoint2.DistanceTo(xyz2);
				if (Geometry.LessThan(num4, num5))
				{
					element3 = grid;
					xyz6 = xyzpoint;
					xyz7 = xyz2;
				}
				else
				{
					element3 = wall;
					xyz6 = xyzpoint2;
					xyz7 = xyz3;
				}
			}
			else if (wall == null && grid != null)
			{
				Curve curve3 = grid.Curve.Clone();
				curve3.MakeUnbound();
				XYZ xyzpoint3 = curve3.Project(xyz2).XYZPoint;
				element3 = grid;
				xyz6 = xyzpoint3;
				xyz7 = xyz2;
			}
			else if (wall != null && grid == null)
			{
				Curve curve4 = (wall.Location as LocationCurve).Curve.Clone();
				curve4.MakeUnbound();
				XYZ xyzpoint4 = curve4.Project(xyz2).XYZPoint;
				element3 = wall;
				xyz6 = xyzpoint4;
				xyz7 = xyz3;
			}
			if (element3 == null || xyz7 == null)
			{
				return;
			}
			DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz7, fi.FacingOrientation);
			Curve curve5 = (element3.Location as LocationCurve).Curve;
			if (null == curve5 || curve5 is Arc)
			{
				return;
			}
			Line line = curve5 as Line;
			if (element3 is Wall)
			{
				Wall wall2 = element3 as Wall;
				XYZ xyz8 = Geometry.RotateTo(line.Direction, Math.PI*.5, XYZ.BasisZ);
				XYZ xyz9 = xyz6 + xyz8 * (wall2.Width / 2.0);
				XYZ xyz10 = xyz6 - xyz8 * (wall2.Width / 2.0);
				xyz6 = (Geometry.LessThan(xyz7.DistanceTo(xyz9), xyz7.DistanceTo(xyz10)) ? xyz9 : xyz10);
			}
			DetailCurve detailCurveWithPoint2 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz6, line.Direction);
			if (!Geometry.IsParallel(Line.CreateBound(xyz7, xyz7 + fi.FacingOrientation).Direction, Line.CreateBound(xyz6, xyz6 + fi.FacingOrientation).Direction, 1E-09))
			{
				return;
			}
			ReferenceArray referenceArray = new ReferenceArray();
			Reference reference = new Reference(detailCurveWithPoint);
			referenceArray.Append(reference);
			reference = new Reference(detailCurveWithPoint2);
			referenceArray.Append(reference);
			Line line2 = Line.CreateBound(xyz7, xyz7 + fi.HandOrientation);
			Dimension newDim = new SizeDimData(this.m_doc, line2, referenceArray).CreateDim(true);
			this.SetDimPosition(newDim, line2, line2.Direction.CrossProduct(XYZ.BasisZ));
		}

		private void CreateParallelDim(double dMax, double dWidth, FamilyInstance fi, XYZ vtOffset, XYZ vtNewOffset, XYZ ptLocation)
		{
			XYZ xyz = ptLocation + vtOffset * (dMax / 2.0);
			XYZ xyz2 = xyz + vtNewOffset * (dWidth / 2.0);
			XYZ xyz3 = xyz - vtNewOffset * (dWidth / 2.0);
			List<XYZ> list = new List<XYZ>();
			list.Add(xyz2);
			list.Add(xyz3);
			Grid grid = null;
			Element element = null;
			XYZ xyz4 = null;
			double maxValue = double.MaxValue;
			this.GetWallMinDim(ref element, ref xyz4, ref maxValue, fi.HandOrientation, xyz);
			DbAxial dbAxial = null;
			double maxValue2 = double.MaxValue;
			if (base.GetDbAxialWithDir(fi.HandOrientation, out dbAxial))
			{
				grid = dbAxial.GetGridNearestXZY(xyz, ref maxValue2);
			}
			Element element2 = null;
			if (element != null && grid != null)
			{
				if (Geometry.LessThan(maxValue, maxValue2))
				{
					element2 = element;
				}
				else
				{
					element2 = grid;
				}
			}
			else if (element == null && grid != null)
			{
				element2 = grid;
			}
			else if (element != null && grid == null)
			{
				element2 = element;
			}
			if (element2 != null)
			{
				Line line = null;
				if (element2 is Wall)
				{
					line = (((element2 as Wall).Location as LocationCurve).Curve as Line);
				}
				else
				{
					Curve curve = (element2 as Grid).Curve;
					if (curve is Line)
					{
						line = (curve as Line);
					}
				}
				if (null != line && Geometry.IsParallel(Line.CreateBound(xyz2, xyz2 + fi.HandOrientation).Direction, line.Direction, 1E-09))
				{
					if (line.IsBound)
					{
						line.MakeUnbound();
					}
					XYZ xyz5 = line.Project(xyz2).XYZPoint;
					xyz5 = new XYZ(xyz5.X, xyz5.Y, xyz2.Z);
					list.Add(xyz5);
				}
			}
			AssistFunc.CompressArray(list);
			ReferenceArray referenceArray = new ReferenceArray();
			foreach (XYZ startPoint in list)
			{
				DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, startPoint, fi.HandOrientation);
				if (detailCurveWithPoint != null)
				{
					Reference reference = new Reference(detailCurveWithPoint);
					referenceArray.Append(reference);
				}
			}
			Line line2 = Line.CreateBound(xyz2, xyz3);
			Dimension newDim = new SizeDimData(this.m_doc, line2, referenceArray).CreateDim(true);
			this.SetDimPosition(newDim, line2, line2.Direction.CrossProduct(XYZ.BasisZ));
		}

		private void DitchClassification(List<ElementId> lstEleId, Dictionary<double, List<FamilyInstance>> dic)
		{
			foreach (ElementId eleId in lstEleId)
			{
				Element element = CommonInterface.GetElement(eleId, KeyComponent.GetInstance().m_lstDoc);
				if (element.Category.Id.IntegerValue == -2001350)
				{
					Parameter parameter = RevitElementExtension.GetParameter(element, "宽度");
					if (parameter != null)
					{
						double num = parameter.AsDouble();
						parameter = RevitElementExtension.GetParameter(element, "壁厚");
						if (parameter != null)
						{
							double num2 = parameter.AsDouble();
							double num3 = num + num2 * 2.0;
							bool flag = true;
							foreach (double num4 in dic.Keys)
							{
								if (Geometry.IsEqual(num4, num3))
								{
									dic[num4].Add(element as FamilyInstance);
									flag = false;
									break;
								}
							}
							if (flag)
							{
								dic.Add(num3, new List<FamilyInstance>
								{
									element as FamilyInstance
								});
							}
						}
					}
				}
			}
		}

		private const string m_strLength = "长度";

		private const string m_strWidth = "宽度";

		private const string m_strWallThickness = "壁厚";

		private Group m_Ditch;
	}
}
